<template>
  <div id="app">
    <div ref="ChartRef" class="progressChart"></div>
  </div>
</template>

<script setup>
import * as echarts from 'echarts'
import { ref, onMounted, watch, nextTick, computed } from 'vue'
const isYear = ref(true)
const ChartRef = ref()
const BAR_HEIGHT = 32 // 每个条的高度
const MIN_HEIGHT = 400 // 你可以根据实际情况调整
let progressChart
const rawData = ref([
  {
    name: '任务一',
    planStart: '2021-01-05',
    planEnd: '2021-01-15',
    actualStart: '2021-01-06',
    actualEnd: '2021-01-16',
  },
  {
    name: '任务二',
    planStart: '2021-02-01',
    planEnd: '2021-02-28',
    actualStart: '2021-02-02',
    actualEnd: '2021-02-12',
  },
  {
    name: '任务三',
    planStart: '2021-03-05',
    planEnd: '2021-03-15',
    actualStart: '2021-03-06',
    actualEnd: '2021-03-16',
  },
])
// 点击1月
// const rawData1 = ref([
//   {
//     name: '任务一',
//     planStart: '2021-01-05',
//     planEnd: '2021-01-15',
//     actualStart: '2021-01-06',
//     actualEnd: '2021-01-16',
//   },
// ])
// 2月(跨月截断)
const rawData2 = ref([
  {
    name: '任务二',
    planStart: '2021-02-01',
    planEnd: '2021-03-10',
    actualStart: '2021-02-02',
    actualEnd: '2021-02-12',
  },
])

const getYAxisData = () => {
  // TODO 按照isYear 区分
  if (isYear.value) {
    return rawData.value.map((item) => item.name) || []
  } else {
    return rawData2.value.map((item) => item.name) || []
  }
}
const yearData = ref({
  planStartTime: computed(() => rawData.value.map((item) => item.planStart) || []),
  planEndTime: computed(() => rawData.value.map((item) => item.planEnd) || []),
  actualStartTime: computed(() => rawData.value.map((item) => item.actualStart) || []),
  actualEndTime: computed(() => rawData.value.map((item) => item.actualEnd) || []),
})
console.log('yearData:', yearData.value)
const monthData = ref({
  planStartTime: computed(() => rawData2.value.map((item) => item.planStart) || []),
  planEndTime: computed(() => rawData2.value.map((item) => item.planEnd) || []),
  actualStartTime: computed(() => rawData2.value.map((item) => item.actualStart) || []),
  actualEndTime: computed(() => rawData2.value.map((item) => item.actualEnd) || []),
})
console.log('monthData:', monthData.value)

// 获取计划时间
const getPlanOptions = () => {
  const option = {
    name: '计划时间',
    type: 'bar',
    stack: 'duration',
    zlevel: -1,
  }
  // TODO isYear
  return [
    // 结束时间
    {
      ...option,
      itemStyle: {
        color: '#7ED6F9',
        borderColor: '#fff',
        borderWidth: 1,
      },
      data: isYear.value
        ? yearData.value.planEndTime.map((item) => item + ' 23:59:59')
        : monthData.value.planEndTime.map((item) => item + ' 23:59:59'),
    },
    // 开始时间
    {
      ...option,
      itemStyle: {
        color: '#fff',
      },
      z: 9, // z值小的图形会被z值大的图形覆盖，z相比zlevel优先级更低，而且不会创建新的 Canvas
      data: isYear.value
        ? yearData.value.planStartTime.map((item) => item + ' 00:00:00')
        : monthData.value.planStartTime.map((item) => item + ' 00:00:00'),
    },
  ]
}

// 获取完成时间
const getActualOptions = () => {
  const option = {
    name: '实际完成',
    type: 'bar',
    stack: 'real',
    zlevel: -1,
  }
  // TODO isYear
  return [
    //结束时间
    {
      ...option,
      itemStyle: {
        color: '#FFC04D',
        borderColor: '#fff',
        borderWidth: 1,
      },
      data: isYear.value
        ? yearData.value.actualEndTime.map((item) => item + ' 23:59:59')
        : monthData.value.actualEndTime.map((item) => item + ' 23:59:59'),
    },
    // 开始时间
    {
      ...option,
      itemStyle: {
        color: '#fff',
      },
      z: 9, // z值小的图形会被z值大的图形覆盖，z相比zlevel优先级更低，而且不会创建新的 Canvas
      data: isYear.value
        ? yearData.value.actualStartTime.map((item) => item + ' 00:00:00')
        : monthData.value.actualStartTime.map((item) => item + ' 00:00:00'),
    },
  ]
}
const getOption = () => {
  const allDates = [...yearData.value.actualStartTime, ...yearData.value.actualEndTime].map((item) => item.slice(0, 10))
  const minYear = Math.min(...allDates.map((date) => new Date(date).getFullYear()))
  const xAxisMin = isYear.value ? `${minYear}-01-01 00:00:00` : undefined

  return {
    // 鼠标移入提示工具
    tooltip: {
      trigger: 'axis',
      formatter(params) {
        if (params[1].data && params[0].data) {
          const name = params[0].name
          // 获取计划时间的 marker 和文本
          const planMarker = params[0].marker
          const planText = params[0].seriesName

          // 获取实际时间的 marker 和文本
          const actualMarker = params[2].marker
          const actualText = params[2].seriesName

          return (
            `${name}<br/>` +
            `${planMarker}${planText}<br/>` +
            `开始时间：${params[1].data.split(' ')[0]}<br/>` +
            `结束时间：${params[0].data.split(' ')[0]}<br/>` +
            `${actualMarker}${actualText}<br/>` +
            `开始时间：${params[3].data.split(' ')[0]}<br/>` +
            `结束时间：${params[2].data.split(' ')[0]}`
          )
        } else {
          return ''
        }
      },
      axisPointer: {
        type: 'shadow',
      },
    },
    grid: {
      containLabel: true,
      left: 20,
      right: 80,
      bottom: 40,
      top: 20,
      backgroundColor: '#fff',
    },
    legend: {
      // 图例组件
      data: ['计划时间', '实际完成'],
      align: 'auto',
      top: 'bottom',
    },
    xAxis: {
      min: xAxisMin,
      triggerEvent: true,
      type: 'time',
      position: 'top',
      axisTick: {
        show: false,
      },
      axisLine: {
        show: true,
      },
      splitLine: {
        show: false,
      },
      axisLabel: {
        fontSize: 16,
        formatter: isYear.value
          ? function (value) {
              const date = new Date(value)
              const month = date.getMonth() + 1
              if (isYear.value) {
                if (date.getDate() === 1) {
                  return `${month}月`
                }
                return ''
              } else {
                const day = date.getDate()
                return `${month}月${day}日`
              }
            }
          : {
              month: '{MM}月', // 一月、二月、……
              day: '{dd}日', // 1日、2日、……
            },
      },
    },
    yAxis: {
      inverse: true,
      axisTick: { show: false },
      axisLine: { show: true },
      splitLine: { show: true },
      axisLabel: {
        fontSize: 14,
        margin: 8,
        interval: 0,
        rotate: 30,
      },
      data: getYAxisData(),
    },
    series: [...getPlanOptions(), ...getActualOptions()],
    dataZoom: [
      {
        type: 'slider',
        yAxisIndex: [0],
        right: 10,
        width: 20,
        start: 0,
        end: 40,
        moveOnMouseWheel: true, //鼠标滚轮平移
        zoomOnMouseWheel: false, //鼠标滚轮缩放
        // moveOnMouseMove: true, // 鼠标拖动平移
        handleSize: 8,
        handleStyle: {
          color: '#7ED6F9',
          borderColor: '#7ED6F9',
        },
        moveHandleStyle: {
          color: '#7ED6F9',
        },
        fillerColor: 'rgba(126, 214, 249, 0.2)',
        borderColor: 'transparent',
      },
      {
        type: 'inside',
        yAxisIndex: [0],
        moveOnMouseWheel: true,
        zoomOnMouseWheel: false,
        // moveOnMouseMove: true, // 鼠标拖动平移
      },
    ],
  }
}

const setChartHeight = () => {
  const taskCount = getYAxisData().length
  if (ChartRef.value) {
    const height = Math.max(taskCount * BAR_HEIGHT, MIN_HEIGHT)
    ChartRef.value.style.height = height + 'px'
  }
}

const initChart = () => {
  if (!ChartRef.value) return
  setChartHeight() // 关键：每次初始化都设置高度
  progressChart?.dispose?.()
  progressChart = null
  progressChart = echarts.init(ChartRef.value)
  // 获取数据
  const option = getOption()
  progressChart.setOption(option)
  // 浏览器窗口大小变化，图表大小自适应
  window.addEventListener('resize', () => {
    progressChart.resize()
  })

  progressChart.on('click', function (params) {
    if (params.componentType === 'xAxis') {
      if (isYear.value) {
        // 如果是在年度视图点击，切换到月度视图并设置选中的月份
        isYear.value = false
      } else {
        // 如果是在月度视图点击，切换回年度视图
        isYear.value = true
      }
    }
  })
}

watch(
  () => isYear.value,
  () => {
    nextTick(() => {
      console.log('isYear.value:', isYear.value)

      initChart()
    })
  },
)
onMounted(() => {
  nextTick(() => {
    initChart()
  })
})
</script>

<style scoped>
#app {
  display: flex;
  justify-content: center;
  align-items: center;
}
.progressChart {
  width: 60%;
  /* height: 400px; */ /* 不要写死高度 */
}
</style>
